home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1996 April
/
CHIP 1996 aprilis (CD06).zip
/
CHIP_CD06.ISO
/
hypertxt.arj
/
9410
/
386_3.CD
< prev
next >
Wrap
Text File
|
1994-11-23
|
19KB
|
325 lines
@VVédett módú grafikai példaprogram@N
@VModern idôk -- III.@N
Sorozatunk második részében a 386-os védett módjába való
belépés és az az alatti programozás elméleti alapjaival
foglalkoztunk.
Ezúttal a gyakorlati megvalósítást tárgyaljuk egy, a VGA
memóriáját lineárisan címzô grafikus példaprogram kapcsán.
@KAz assembly forráslistát -- annak hossza miatt -- itt nem@N
@Kközöljük, az érdeklôdôk szerkesztôségünkben megkaphatják.@N
@KA file 386_3.ARJ néven a CT BBS-en is megtalálható. (Tel.:@N
@K140-9312, minden este 6-tól reggel 9 óráig.)@N
@VA 80386 védett módjának használata nagyvonalakban@N
A 80386 processzor védett módban való használatához
elengedhetetlenül szükséges a CPU által használt
vezérlôregiszterek és memóriatáblázatok elôzetes feltöltése
és a hardver megfelelô átállítása. E tevékenységet és
néhány biztonsági ellenôrzést a szakirodalomban System
Builder néven említett programrész végzi el, a program
memóriában elfoglalt helyzetének függvényében.
Feladatainak végeztével a processzor CR0 regiszterének
beállításával a processzort védett módba lépteti, majd --
távoli ugrással törölve a CPU elôolvasási tárát --
elindítja a System Kernel nevû felügyelô programot.
A Kernel felel a teljes, védett módban futó rendszer
mûködéséért. Feladata a taszkok (egyes feladatok vagy
alprogramok) indítása, a processzoridô és az erôforrások
helyes megosztása, az esetlegesen fellépô hibák kezelése,
valamint a virtuális memória lapozása. A Kernel feladatai
közé tartozik a védett módú futás alatt fellépô DOS vagy
BIOS I/O igény valós módú visszalépésekkel vagy V86 taszk
nyitásával való teljesítése. Ha a rendszerbôl való végleges
kilépésre van szükség, a Kernel zárja le a futó taszkokat,
törli a virtuális memória lemezen elhelyezkedô részeit,
valamint visszaállítja a szegmensek és a CR0 regiszter
valós módban használatos értékeit.
E rövid áttekintô ismertetés után lássuk részletesen az
egyes lépéseket. A példaprogram természetesen változtatás
nélkül futtatható az összes, IBM AT 386 számítógéppel
védett módban is teljesen kompatibilis rendszerben, de nem
futtatható olyan memóriakezelô program felügyelete alatt,
amely már korábban védett módba kapcsolt (például: EMM386,
QEMM, NetRoom), s nem futtatható a Windows felügyelete
alatt sem. E cikksorozat és a szöveglistákban lévô
megjegyzések alapján bárki, aki érdeklôdik a 80386 assembly
nyelven való védett módú programozása után, megértheti az
ehhez szükséges legelemibb ismereteket.
Mûködô példaprogram híján kénytelen voltam az eredeti Intel
processzorleírás használatával -- és némi hardver
ismerettel -- magamtól kiszenvedni egyet. (Az általam
ismert szakirodalom nem foglalkozott 386-os AT alaplap
átprogramozásával, csak a processzor védett módba
léptetésével.) Nem hiszem, hogy egyedül fel lehet venni a
versenyt a nagy védett módú operációs rendszerekkel és
memóriamenedzser programokkal, de úgy gondolom, hogy a
védett módú programozás ismerete elôsegíti az egyre jobb --
kompatibilitást nem igénylô -- képfeldolgozó, zenei, játék
és demó programok fejlesztését.
@VA System Builder@N
Rövid bejelentkezô felirat kiíratása után a System Builder
ellenôrzi a szabad DOS memória méretét, valamint azt, hogy
V86 taszkban, egy már futó System Kernel felügyelete alatt
fut-e. Már futó védelmi rendszer esetén a 0. védelmi szint
elérése, és a rendszer felépítése nem lehetséges, minden,
rendszerregiszterbe való írási kísérlet kizárást hozna
létre. V86 taszk esetén az új System Builder hibaüzenettel
kilép. Az ellenôrzést a CR0 0. bitjének (PE = Protection
Enable) tesztelésével végzi el, amelynek 1 értéke jelzi,
hogy a processzor már védett módban van.
Mivel a kontroll regisztereknek (CRx) és az EFlags
regiszternek nagy jelentôsége van a védett módú
programozásban, részletesen elmagyarázom felépítésüket
(lásd a ""CRx és EFLAGS" ábrát). A fenntartott és üresen
hagyott biteket nullára kell állítani a késôbbi Intel
processzorokkal való kompatibilitás miatt. Léteznek még a
tesztelést (TRx) és nyomkövetést (DRx) elôsegítô
vezérlôregiszterek is, de ezek használata nem feltétlenül
szükséges egy védett módú rendszer futásához, inkább csak
diagnosztikai és debugger programok írásához. Bitenkénti
felosztásukat késôbbi cikkemben fogom megadni. 80386
processzorra írt programokban nem javasolt a CR1 regiszter
bárminemû felhasználása.
Ha a processzor még valós módban leledzik, a System Builder
feladata a védett módú futás elôkészítése. Külön
szegmenseken, 16-tal osztható címekre elhelyezi a globális
és interruptleíró táblázatokat, melyekben az 1 Mbyte alatti
lineáris címek kitöltését a program aktuális címének
megfelelôen, futásidôben kell elvégezni. Ezután megkeresi
az elsô, 4096-tal osztható szabad címet (laphatárt) a
memóriában, ahol felépíti a lapkönyvtárat és az elsô öt
laptáblát, ami 20 Mbyte lapszervezésû virtuális memória
címzését teszi lehetôvé. A program az ötödik laptábla
felhasználásával a lineáris címtartomány 16 Mbyte feletti 4
Mbyte méretû részével lehetôvé teszi az SVGA grafikus
kártyákon elhelyezett, maximum 4 Mbyte méretû RAM
virtualizálását nem lapozott, folyamatos címterületté. Ez a
szervezés jelentôsen megkönnyíti a nagyfelbontású képernyôt
használó grafikus programok írását. A példaprogram a
kompatibilitás miatt a standard VGA kártyák által is ismert
360*480 felbontású 256 színû üzemmódot használja, de az
inicializáló és a lapozó rutinok cseréjével ez bármely
kártya bármely üzemmódjára átültethetô. Ezzel a megoldással
akár hardver EMS kártyák memóriája is lineáris
címtartománnyá alakítható.
A lineáris címtartomány elsô 1 Mbyte-ja a Kernel és a DOS
memória állandó elérhetôsége miatt a fizikai memória azonos
címtartományára mutat.
Az inicializálás további része tiltott interrupt állapotban
kell fusson, mert bármely interrupt elfogadása hibára
vezethet félig beállított processzorállapot esetén. Az IBM
AT alaplapokon lehetôség van az NMI interrupt hardverrel
való maszkolására, amit a program idôlegesen igénybe is
vesz. Elsô feladat a még futtatható HIMEM.SYS segítségével
az A20 címvezeték engedélyezése az extended memória
elérésére, valamint az esetleges XMS foglaltság
ellenôrzése. Elônyösebb lenne, ha ezt a mûveletet sem
kellene más programra bízni, de hála a különbözô alaplapok
zseniális tervezôinek és gyártóinak, az A20 címvezeték
maszkolása szinte minden típuson más és más.
Az A20 címvezeték sikeres engedélyezése után az interrupt
vezérlô átállítása következik. Mint köztudott, az IBM AT
gépek IRQ0-7 vezetékei az INT 08H-0FH, IRQ8-15 vezetékei
pedig az IRQ2 kaszkád vonalon keresztül az INT 70H-77H
megszakításokat váltják ki. A 80386 processzor azonban
kizárások feldolgozására tartja fent az INT 00H-1FH
megszakítási vektorokat, ami miatt legalább az IRQ0-7
vonalak megszakítási vektorait át kell irányítani a
processzor által szabadon hagyott INT vektorok egy
csoportjára. A példaprogram az INT 20H-2FH vektorokat
használja a hardver interruptok fogadására. A CPU védett
módra való felkészítése néhány utasítással elvégezhetô.
Elsô a CR3 regiszter beállítása, melybe a lapkönyvtár
fizikai címét kell betölteni az ábra szerint. Ez az
egyetlen fizikai címként értelmezett regiszter a rendszer
teljes futásideje alatt. Az LIDT és LGDT utasítások
használatával a System Builder betölti az interrupt és
globális leíró táblázatok leíróit a processzor IDTR és GDTR
szegmensleíró regisztereibe. Végül a CR0 0. és 31.
bitjének egyes értékbe állításával engedélyezi a védett
módú címzést és a lapozóáramkör mûködését. Végül egy távoli
ugrással törli a processzor elôolvasási tárát, és átadja a
vezérlést az immár védett módban futó System Kernelnek.
@VA System Kernel@N
A System Kernel felügyelô program elsô feladata a gépben
fellelhetô memória linearizálása, saját taszkállapot
szegmens (TSS=Task State Segment) létrehozása, továbbá a
billentyûzet és timer interruptok, valamint a legfontosabb
kizárások kezelése. A példaprogram létrehozza ugyan saját
taszkállapot szegmensét, de nem használja. Ez az egyszerû
rendszer még csak 0. védelmi szinten, egy taszkban fut. A
taszkok részletes ismertetése következô cikkem témája lesz.
Elôzetesen leírom a 80386 által használt 32 bites TSS
felépítését (lásd a ""TSS felépítése" címû ábrát!).
A System Kernel feladata még a koprocesszor védett módba
állítása és virtualizálása, amit kisebb jelentôsége és
helyhiány miatt szintén egy késôbbi cikkemben mutatok majd
be.
A linearizálás a memória méretének ellenôrzésébôl és a
laptábla helyes kitöltésébôl áll. A példaprogram lehetôvé
teszi 15 Mbyte virtuális memória létrehozását a szabad DOS
memória és a teljes XMS memória felhasználásával. A
példaprogram XMS nélkül, 1 Mbyte RAM-mal rendelkezô
alaplapon is futtatható.
A példaprogram által használt virtuális memória
lapszervezésû. E virtuális memória bármely nem jelenlévô
(fizikai memóriában nem elérhetô) lapjára való hivatkozás
laphibát vált ki. A laphiba kizárás lapcserét kezdeményez,
amely valós módba való gyors visszalépések létrehozásával
-- valós módú DOS hívások felhasználásával -- behívja a
hiányzó lapot az elôre meghatározott file-ból. Ha a lap
behívására nincsen szabad lap a fizikai memóriában, a
lapozó feladata -- a lapozási stratégiának megfelelôen -- a
legkevésbé vagy legrégebben használt lap törlése a
virtuális memóriából. A laptábla megfelelô módosítása után
a laphibát kezelô rutin a processzor CR3 regiszterének
újratöltésével (azonos értékre is lehet) törli a processzor
belsô lapfordítást gyorsító tárát, a TLB-t (Translation
Lookaside Buffer). A TLB-ben a processzor az utolsó 32
sikeres lapfordítás eredményét tárolja a laptáblához való
sûrû és idôpocsékoló hozzáférés elkerülésére. Ezek között a
laptábla módosítása miatt már nem aktuális eredmény is
lehet. Az így betöltött területek tartalma szabadon
megváltoztatható, de az egyszerûség kedvéért a példaprogram
a változásokat még nem írja vissza az adott file-ba.
A lapozáshoz használt DOS visszalépés teljes valós módú
visszatérés, amit a védett módú program bármikor, más célra
is igénybe vehet. Ennek során a védett módhoz kapcsolódó
teljes rendszerállapot mentésre kerül. A valós módban futó
rutin memóriában tárolt értékeket és általános
regisztereket adhat át a védett módú programnak és viszont.
A szegmensregiszterek értéke nem kerülhet átadásra a valós
módú rutinnak, így azok visszatérés után változatlanok
lesznek. A valós módú rutin bármely szegmensregiszter
értékét szabadon módosíthatja, visszaállításuk nem
kötelezô.
A timer interrupt (IRQ0) kezelése a lapozás
optimalizálására és az idôosztás taszkváltásaira egyaránt
használható. A timer vezérlésére használható elsôsorban.
Felprogramozása a védett módba való minden belépéskor
szükséges.
A billentyûzet interrupt (IRQ1) kezelése lehetôséget ad az
aktív taszk váltására, lezárására és a rendszerbôl való
gyors kilépésre. A példaprogram csak képkirakásra ([1-[4]
gombok), funkcióválasztásra ([5-[8]) és kilépésre ([Esc)
használja a billentyûzetet. A billentyûzetkezelôbe be van
építve egy lefagyás esetén alkalmazható vészkilépés a
[SysRq] gomb használatával.
@VKilépés valós módba@N
Sokszor szükséges, hogy reset használata nélkül lehessen
visszaléptetni a rendszert védett módból valós módba. Erre
a 80386 processzor lehetôséget ad a CR0 regiszter 0.
bitjének törlésével, de visszalépés elôtt a processzort és
a hardvert vissza kell állítani valós módra, enélkül a DOS
mûködésképtelen. Elsô teendô a megszakítások szokásos
tiltása. Ezt követi a szegmensregiszterek 65535 limit
értékû és valós módnak megfelelô bázisértékû feltöltése az
alsó 1 Mbyte lineáris címterületen. A laptábla e szegmensek
területén a logikai címekkel megegyezô fizikai címekre
kell, hogy mutasson. Az interrupt vezérlô és a timer
gyakoriság visszaprogramozása után következhet a CR0 0. és
31. bitjének törlése. Egy távoli ugrással frissíteni kell
az elôolvasási tárat, majd IDTR értékét 0 bázisú és 03FFH
limit értékû leíróval kell feltölteni. A GDTR-t nem kell
visszaprogramozni. Érdemes a BIOS adatterületen az [Alt],
[Shift] és [Ctrl] billentyûk esetleges lenyomott
állapotjelzésének törlése a bosszúságok elkerülésére. Az
interruptok engedélyezése után a DOS mûködôképes,
amennyiben memóriaterületei sértetlenek.
@VTanácsok védett módú programok írásához@N
A megszakítások kiosztását és a memóriaszervezést --
fôképpen a lapozásnál -- gondosan tervezzük meg a lehetô
legegyszerûbbre és leggyorsabbra. A laptáblákat és a
leírótáblákat a bôvíthetôség érdekében vegyük nagyobbra a
szükségesnél. A használatlan elemeket mindig töltsük ki
valamilyen nyomonkövethetô jelzéssel, hogy ha hibát okoz,
biztosan tudjuk, hol és miért. Védett módú debugger
hiányában ez nagyon hasznos lehet. A nem használt interrupt
vektorokat is minden esetben irányítsuk át egy hibakezelô
rutinra a könnyebb hibakeresés érdekében. A hibakezelô
térjen vissza valós módba, majd -- szöveges képernyô
beállítása után -- írja ki az interrupt sorszámát, a
regisztereket, esetleg a stack tetejének néhány duplaszavát
is.
Ne használjunk DOS által relokált távoli ugrásokat és
szegmenscímeket. Mindig hozzunk létre helyettük
pointereket adat- vagy kódszegmensen.
A DOS-szal való ütközés elkerülésére csak az alsó 640 Kbyte
szabadon maradó részeit és az extended memória 1088 Kbyte
feletti részét használjuk programjainkban. Ne hagyjunk
bent XMS-t használó memóriarezidens segédprogramokat
(például Norton Cache) futtatáskor, mivel tárterületeik
felülírása katasztrofális következményekkel járhat. Ez
ellen védekezhetünk a szabad extended memória XMM-tôl (ez
általában a HIMEM.SYS) való lekérdezésével.
Valós módba való rövid visszatéréseknél mindig tartsuk szem
elôtt, hogy az átprogramozott hardver interruptok valós
módban is bekövetkezhetnek.
Védett módban a kódszegmensek sohasem írhatók, így írni
kívánt változókat mindig adatszegmensre tegyünk. A
szegmensregisztereket mindig töltsük fel érvényes
szelektorral, vagy ha nem használtak, nullával. A
szegmensek határait (utolsó használt byte címe) mindig
pontosan adjuk meg a túlcímzések felderítésére. A
szegmensek adatterületei jó ha a lapozáshoz illeszkedve
laphatáron kezdôdnek (4096-tal osztható lineáris címek).
Minden kódszegmensben a leírótáblával megegyezôen adjuk meg
az adathossz alapbeállítását a USE16 vagy USE32 kulcsszóval
a kódszegmens definíciójának végén.
Figyeljünk a lapozható memóriák (video, hardver EMS)
linearizálásánál a laphatárokon fellépô hibalehetôségre. Ha
WORD vagy DWORD címzôdik laphatáron átlógó résszel, a
lapozó hívása végtelen hurokba szalad. E hiba elkerülhetô
egy lap (4096 byte) hozzáfûzésével. A módszer
idôveszteséget és plusz lapozást igényel, így figyeljünk az
ilyen címzések elkerülésére. A beiktatott 4096 byte-os
lapot csak akkor kell visszaírni, ha a laptáblában az adott
laphoz tartozó Dirty bit értéke 1 lett.
Kellemes kísérletezést!
@KFerenczi Viktor@N
@<9410\386_3_1.GIF>A kontroll és EFLAGS regiszterek felépítése@N
@<9410\386_3_2.GIF>A TSS felépítése@N